/* =========================================
 *      用户管理子服务的客户端测试搭建 
 * =========================================*/

#include "etcd.hpp"
#include "channel.hpp"
#include "base.pb.h"
#include "file.pb.h"
#include "user.pb.h"
#include "utils.hpp"
#include <brpc/controller.h>
#include <gflags/gflags.h>
#include <google/protobuf/map.h>
#include <gtest/gtest.h>
#include <iostream>
#include <string>
#include <chrono>
#include <thread>

DEFINE_bool(run_mode, false, "程序的运行模式: false-调试 true-发布");
DEFINE_string(log_file, "", "指定日志的输出文件");
DEFINE_int32(log_level, 0, "指定日志输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(user_service, "/service/user_service", "当前监控的服务");

shared::infra::RpcServiceManagerPtr rpcServiceMgr;
im_proto::UserInfo userInfo;
std::string codeId;
std::string loginSessionId;

void getVerifyCode(const std::string& phone)
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::PhoneVerifyCodeReq req;
    req.set_phone_number(phone);

    brpc::Controller controller;
    im_proto::PhoneVerifyCodeRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.GetPhoneVerifyCode(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
    codeId = resp.verify_code_id();
    std::cout << "codeId: " << codeId <<'\n';
}

// 用户注册功能单元测试
TEST(UserSeriveceTest, UserRegister) 
{
    // 获取用户子服务的rpc通信信道
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    // 模拟用户数据
    userInfo.set_user_id(shared::Uuid::createUuid());
    userInfo.set_nickname("outlier");
    userInfo.set_phone("15935725866");

    // 构造rpc请求
    getVerifyCode(userInfo.phone());
    im_proto::UserRegisterReq req;
    req.set_request_id(userInfo.user_id());
    req.set_nickname(userInfo.nickname());
    req.set_password("159357");
    req.set_phone_number(userInfo.phone());
    req.set_verify_code_id(codeId);
    std::cout << "【用户注册】输入验证码：" << '\n';
    std::string code;
    std::cin >> code;
    req.set_verify_code(code);

    // rpc响应校验
    brpc::Controller controller;
    im_proto::UserRegisterRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.UserRegister(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
}

// 用户账号登录功能单元测试
TEST(UserSeriveceTest, AccountLogin) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::AccountLoginReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_nickname(userInfo.nickname());
    req.set_password("159357");

    brpc::Controller controller;
    im_proto::AccountLoginRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.AccountLogin(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
    loginSessionId = resp.login_session_id();
}

// 手机号登录功能单元测试
TEST(UserSeriveceTest, PhoneLogin) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    getVerifyCode(userInfo.phone());
    im_proto::PhoneLoginReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_phone_number(userInfo.phone());
    req.set_verify_code_id(codeId);
    std::cout << "【用户登录】输入验证码：" << '\n';
    std::string code;
    std::cin >> code;
    req.set_verify_code(code);

    brpc::Controller controller;
    im_proto::PhoneLoginRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.PhoneLogin(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
    loginSessionId = resp.login_session_id();
}

// 用户手机号修改单元测试
TEST(UserSeriveceTest, UserPhoneSet) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    // userInfo.set_phone("15995148621");
    userInfo.set_phone(userInfo.phone());
    im_proto::SetUserPhoneNumberReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id(userInfo.user_id());
    req.set_phone_number(userInfo.phone());
    req.set_session_id(loginSessionId);
    getVerifyCode(req.phone_number());
    req.set_phone_verify_code_id(codeId);
    std::cout << "【更绑手机号】输入验证码：" << '\n';
    std::string code;
    std::cin >> code;
    req.set_phone_verify_code(code);

    brpc::Controller controller;
    im_proto::SetUserPhoneNumberRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.SetUserPhoneNumber(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
}

// 用户昵称修改单元测试
TEST(UserSeriveceTest, UserNicknameSet) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::SetUserNicknameReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id(userInfo.user_id());
    req.set_nickname("outlier-new");
    req.set_session_id(loginSessionId);

    brpc::Controller controller;
    im_proto::SetUserNicknameRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.SetUserNickname(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
}

// 用户签名修改单元测试
TEST(UserSeriveceTest, UserDescriptionSet) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::SetUserDescriptionReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id(userInfo.user_id());
    req.set_description(userInfo.description());
    req.set_session_id(loginSessionId);

    brpc::Controller controller;
    im_proto::SetUserDescriptionRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.SetUserDescription(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
}

// 用户头像修改单元测试
TEST(UserSeriveceTest, UserAvatarSet) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::SetUserAvatarReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id(userInfo.user_id());
    req.set_avatar(userInfo.avatar());
    req.set_session_id(loginSessionId);

    brpc::Controller controller;
    im_proto::SetUserAvatarRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.SetUserAvatar(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());

    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id("uid1");
    req.set_avatar("uid1's avatar");
    controller.Reset();
    stub.SetUserAvatar(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());

    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id("uid2");
    req.set_avatar("uid2's avatar");
    controller.Reset();
    stub.SetUserAvatar(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());
}

// 获取用户信息单元测试
TEST(UserSeriveceTest, GetUserInfo) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::GetUserInfoReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.set_user_id(userInfo.user_id());

    brpc::Controller controller;
    im_proto::GetUserInfoRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.GetUserInfo(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());

    ASSERT_EQ(resp.user_info().user_id(), userInfo.user_id());
    ASSERT_EQ(resp.user_info().nickname(), userInfo.nickname());
    ASSERT_EQ(resp.user_info().description(), userInfo.description());
    ASSERT_EQ(resp.user_info().phone(), userInfo.phone());
    ASSERT_EQ(resp.user_info().avatar(), userInfo.avatar());
}

// 获取批量用户信息单元测试
TEST(UserSeriveceTest, GetMutilUserInfo) 
{
    auto channel = rpcServiceMgr->choose(FLAGS_user_service); 
    ASSERT_TRUE(channel);

    im_proto::GetMultiUserInfoReq req;
    req.set_request_id(shared::Uuid::createUuid());
    req.add_users_id("uid1");
    req.add_users_id("uid2");
    req.add_users_id(userInfo.user_id());

    brpc::Controller controller;
    im_proto::GetMultiUserInfoRsp resp;
    im_proto::UserService_Stub stub(channel.get());
    stub.GetMultiUserInfo(&controller, &req, &resp, nullptr);
    ASSERT_FALSE(controller.Failed());
    ASSERT_TRUE(resp.success());

    auto user = resp.users_info().at("uid1");
    ASSERT_EQ(user.user_id(), "uid1");
    ASSERT_EQ(user.nickname(), "小美");
    ASSERT_EQ(user.description(), "我是小美");
    ASSERT_EQ(user.phone(), "15599992222");
    ASSERT_EQ(user.avatar(), "uid1's avatar");

    user = resp.users_info().at("uid2");
    ASSERT_EQ(user.user_id(), "uid2");
    ASSERT_EQ(user.nickname(), "小帅");
    ASSERT_EQ(user.description(), "");
    ASSERT_EQ(user.phone(), "14725836999");
    ASSERT_EQ(user.avatar(), "uid2's avatar");

    
    user = resp.users_info().at(userInfo.user_id());
    ASSERT_EQ(user.user_id(), userInfo.user_id());
    ASSERT_EQ(user.nickname(), userInfo.nickname());
    ASSERT_EQ(user.description(), userInfo.description());
    ASSERT_EQ(user.phone(), userInfo.phone());
    ASSERT_EQ(user.avatar(), userInfo.avatar());
}


int main(int argc, char* argv[])
{
    testing::InitGoogleTest(&argc, argv);
    google::ParseCommandLineFlags(&argc, &argv, true);
    shared::init_logger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    // 1.构造rpc服务管理对象
    rpcServiceMgr = std::make_shared<shared::infra::RpcServiceManager>();
    rpcServiceMgr->declared(FLAGS_user_service);   
    auto putCb = std::bind(
        &shared::infra::RpcServiceManager::onServiceOnline, rpcServiceMgr.get(), std::placeholders::_1, std::placeholders::_2
    );
    auto delCb = std::bind(
        &shared::infra::RpcServiceManager::onServiceOffline, rpcServiceMgr.get(), std::placeholders::_1, std::placeholders::_2
    );

    // 2.构造服务发现对象
    shared::infra::DiscoveryPtr client = std::make_shared<shared::infra::Discovery>(
        FLAGS_etcd_host, FLAGS_base_service, putCb, delCb
    );

    userInfo.set_user_id("ab3e-4b2b4999-01");
    userInfo.set_nickname("outlier-new");
    userInfo.set_phone("15995148621");
    userInfo.set_description("I'm outlier, this is a set description test at 2025-07-19");
    userInfo.set_avatar("I'm outlier, his is a set avatar test at 2025-07-19");

    return RUN_ALL_TESTS();
}